package top.lixunda.commerce.common.core.config;

import com.google.gson.Gson;
import feign.Response;
import feign.Util;
import feign.codec.ErrorDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import top.lixunda.commerce.common.core.entity.MessageObject;
import top.lixunda.commerce.common.core.exception.InternalApiException;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author LiXunda
 * @version time:2019/10/29 13:56
 * <p>
 * feign异常解码器，直接抛出InternalApiException异常
 */
@SuppressWarnings({"unused", "Duplicates"})
@Slf4j
public class FeignClientErrorDecoder implements ErrorDecoder {

    private Gson gson = new Gson();

    private ErrorDecoder decoder = new Default();

    public FeignClientErrorDecoder() {
        super();
        log.debug("my config FeignClientErrorDecoder");
    }

    @Override
    public Exception decode(String s, Response response) {
        log.debug("decode response status : " , response.status());
        if (response.status() != HttpStatus.OK.value()) {
            if (response.status() == InternalApiException.DEFAULT_HTTP_STATUS) {
                log.debug("the controller error is {}" , InternalApiException.DEFAULT_HTTP_STATUS);
                String errorContent;
                try {
                    errorContent = Util.toString(response.body().asReader());
                    MessageObject messageObject = gson.fromJson(errorContent, MessageObject.class);
                    InternalApiException exception = new InternalApiException(response.status(), messageObject.getCode(),
                            messageObject.getMsg());
                    log.debug("接收到feign调用传递的InternalApiException异常");
                    log.debug("throw InternalApiException : status = {}, code = {} message = {}" ,
                            exception.getHttpStatus(), exception.getMsgCode(), exception.getMsg());
                    return exception;
                } catch (IOException e) {
                    log.error("handle error exception");
                    return e;
                }
            }
        }
        log.info("controller error : status = {} reason = {}" , response.status(), response.reason());
        //其他异常使用默认
        return decoder.decode(s, response);
    }

    /**
     * 处理response，设置状态码和contentType
     * 通过该方法将返回值设置为HttpStatus.SERVICE_UNAVAILABLE,调用方解析该状态码并继续链式抛出异常
     *
     * @param response 即将返回的response对象
     */
    public static void dealResponse(HttpServletResponse response) {
        if (response != null) {
            response.setStatus(InternalApiException.DEFAULT_HTTP_STATUS);
            response.setContentType("application/json;charset=UTF-8");
        }
    }

}
